﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BusinessEntities;
using DataAccessLayer;
using Draco.Algorithms;
using Draco.DataStructure;

namespace BusinessLayer
{
    public class RestaurantBLL:LocatingPointBLL<Restaurant>
    {
        private D_LinkList<Restaurant> restaurants;

        public D_LinkList<Restaurant> Restaurants { get { return restaurants; } }

        public RestaurantBLL()
        {
            RestaurantDAL dal = new RestaurantDAL();
            restaurants = dal.GetElements();
        }

        #region 查找附近美食

        /// <summary>
        /// 查找指定坐标附近的美食
        /// </summary>
        /// <param name="x">坐标x</param>
        /// <param name="y">坐标y</param>
        /// <param name="errorLevel">允许误差范围</param>
        /// <returns>美食列表</returns>
        public override D_LinkList<Restaurant> GetNearbySites(int x, int y, SeekAdmissibleError errorLevel)
        {
            int hashLen = 8;
            switch (errorLevel)
            {
                case SeekAdmissibleError.Level_1:
                    hashLen = 8;
                    break;
                case SeekAdmissibleError.Level_2:
                    hashLen = 7;
                    break;
                case SeekAdmissibleError.Level_3:
                    hashLen = 6;
                    break;
                case SeekAdmissibleError.Level_4:
                    hashLen = 5;
                    break;
                case SeekAdmissibleError.Level_5:
                    hashLen = 4;
                    break;
                case SeekAdmissibleError.Level_6:
                    hashLen = 3;
                    break;
                case SeekAdmissibleError.Level_7:
                    hashLen = 2;
                    break;
                case SeekAdmissibleError.Level_8:
                    hashLen = 1;
                    break;
            }
            D_GeoHash geo = new D_GeoHash(x, y);
            geo.SetHashLenght(hashLen);
            return GetNearbyRestaurants(geo.GetGeoHashBase4For9());
        }

        private D_LinkList<Restaurant> GetNearbyRestaurants(string geohash)
        {
            D_LinkList<Restaurant> nearby = new D_LinkList<Restaurant>();
            foreach (Restaurant restaurant in Restaurants)
            {
                if (D_String.PrefixMatching(restaurant.GeoHash, geohash))
                {
                    nearby.Add(restaurant);
                }
            }
            return nearby;
        }

        private D_LinkList<Restaurant> GetNearbyRestaurants(D_LinkList<string> geohashs)
        {
            D_LinkList<Restaurant> nearby = new D_LinkList<Restaurant>();
            foreach (Restaurant restaurant in Restaurants)
            {
                foreach (string geohash in geohashs)
                {
                    if (D_String.PrefixMatching(restaurant.GeoHash, geohash))
                    {
                        nearby.Add(restaurant);
                    }
                }
            }
            return nearby;
        }

        #endregion

        public override Restaurant GetSite(int id)
        {
            foreach (Restaurant restaurant in Restaurants)
            {
                if (restaurant.ID == id)
                {
                    return restaurant;
                }
            }
            return null;
        }

        public override void AddSite(Restaurant site)
        {
            //id从数据库获得
            RestaurantDAL dal = new RestaurantDAL();
            dal.Insert(site.Name, site.X, site.Y, site.Grade);
            int id = dal.GetLastInsertID();

            Restaurant temp = new Restaurant(id, site.Name, site.X, site.Y, site.Grade);
            Restaurants.Add(temp);
        }

        public override void UpdateSite(Restaurant site)
        {
            for (int i = 0; i < Restaurants.Count; i++)
            {
                if (Restaurants[i].ID == site.ID)
                {
                    Restaurants[i] = site;
                }
            }
            //更新数据库
            RestaurantDAL dal = new RestaurantDAL();
            dal.Update(site.ID, site.Name, site.X, site.Y, site.Grade);
        }

        public override void DeleteSite(int id)
        {
            int[] array = new int[Restaurants.Count];
            for (int i = 0; i < Restaurants.Count; i++)
            {
                array[i] = Restaurants[i].ID;
            }

            int index = D_Search.BinarySearchIndex(array, id);

            Restaurants.RemoveAt(index);

            //更新数据库
            RestaurantDAL dal = new RestaurantDAL();
            dal.Delete(id);
        }
    }
}
